using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using Lzfy_His_Service.Models;
using Lzfy_His_Service.Repositories;

namespace Lzfy_His_Service.Services
{
    public class AuthService : IAuthService
    {
        private readonly IUserRepository _userRepository;
        private readonly IUumUserService _uumUserService;
        private readonly IConfiguration _configuration;
        private readonly ILoginFailureLimitService _loginFailureLimitService;

        public AuthService(IUserRepository userRepository, IUumUserService uumUserService, IConfiguration configuration, ILoginFailureLimitService loginFailureLimitService)
        {
            _userRepository = userRepository;
            _uumUserService = uumUserService;
            _configuration = configuration;
            _loginFailureLimitService = loginFailureLimitService;
        }

        public async Task<LoginResult> LoginAsync(LoginRequest request)
        {
            try
            {
                // 1. 首先检查用户是否被锁定
                var lockCheckResult = await _loginFailureLimitService.CheckUserLockStatusAsync(request.Username);
                if (lockCheckResult.IsLocked)
                {
                    Console.WriteLine($"用户 {request.Username} 已被锁定，锁定到期时间: {lockCheckResult.LockExpiryTime}");
                    var lockMessage = $"账户已被锁定，请在 {lockCheckResult.LockRemainingMinutes} 分钟后重试";
                    return new LoginResult { ErrorMessage = lockMessage, IsLocked = true };
                }

                // 2. 通过HIS数据库的uum.uum_user表进行鉴权
                var uumUserResponse = await _uumUserService.GetUserByUserNameAsync(request.Username);
                
                if (!uumUserResponse.Success)
                {
                    // 记录登录失败
                    await _loginFailureLimitService.RecordLoginFailureAsync(new RecordLoginFailureRequest
                    {
                        UserName = request.Username,
                        IpAddress = GetClientIpAddress()
                    });
                    return new LoginResult { ErrorMessage = "用户名或密码错误" };
                }
                
                if (uumUserResponse.Data == null)
                {
                    // 记录登录失败
                    await _loginFailureLimitService.RecordLoginFailureAsync(new RecordLoginFailureRequest
                    {
                        UserName = request.Username,
                        IpAddress = GetClientIpAddress()
                    });
                    return new LoginResult { ErrorMessage = "用户名或密码错误" };
                }
                
                var uumUser = uumUserResponse.Data;
                
                if (uumUser.Status != "A")
                {
                    // 记录登录失败
                    await _loginFailureLimitService.RecordLoginFailureAsync(new RecordLoginFailureRequest
                    {
                        UserName = request.Username,
                        IpAddress = GetClientIpAddress()
                    });
                    return new LoginResult { ErrorMessage = "用户账户已被禁用" };
                }

                // 3. 验证MD5密码
                var hashedPassword = HashPasswordMD5(request.Password);
                
                // 首先验证user_password字段
                bool passwordValid = false;
                if (uumUser.UserPassword == hashedPassword)
                {
                    passwordValid = true;
                }
                // 如果user_password验证失败，再验证auth_code字段
                else if (!string.IsNullOrEmpty(uumUser.AuthCode) && uumUser.AuthCode == hashedPassword)
                {
                    passwordValid = true;
                }
                
                if (!passwordValid)
                {
                    // 记录登录失败
                    await _loginFailureLimitService.RecordLoginFailureAsync(new RecordLoginFailureRequest
                    {
                        UserName = request.Username,
                        IpAddress = GetClientIpAddress()
                    });
                    return new LoginResult { ErrorMessage = "用户名或密码错误" };
                }

                // 4. 登录成功，清除失败记录
                await _loginFailureLimitService.ClearLoginFailuresAsync(request.Username);

                // 5. 使用锁机制防止并发登录时的竞争条件
                var lockKey = $"login_{request.Username}";
                lock (GetLockObject(lockKey))
                {
                    var loginResponse = ProcessUserLoginSync(uumUser).Result;
                    return new LoginResult { Response = loginResponse };
                }
            }
            catch (Exception ex)
            {
                // 记录详细的登录错误信息
                Console.WriteLine($"登录过程中发生错误: {ex.Message}");
                Console.WriteLine($"堆栈跟踪: {ex.StackTrace}");
                return new LoginResult { ErrorMessage = "登录过程中发生错误，请稍后重试" };
            }
        }

        private static readonly Dictionary<string, object> _lockObjects = new Dictionary<string, object>();
        private static readonly object _lockObjectsLock = new object();

        private object GetLockObject(string key)
        {
            lock (_lockObjectsLock)
            {
                if (!_lockObjects.ContainsKey(key))
                {
                    _lockObjects[key] = new object();
                }
                return _lockObjects[key];
            }
        }



        private async Task<LoginResponse?> ProcessUserLoginSync(UumUser uumUser)
        {
            // 检查本地users表中是否存在该用户，如果不存在则创建
            var localUser = await _userRepository.GetByUsernameAsync(uumUser.UserName);
            
            if (localUser == null)
            {
                // 创建本地用户记录
                localUser = new User
                {
                    Username = uumUser.UserName ?? string.Empty,
                    PasswordHash = uumUser.UserPassword ?? string.Empty,
                    FullName = uumUser.PeopleName ?? string.Empty,
                    Role = "User", // 默认角色
                    IsActive = true,
                    CreatedAt = DateTime.Now,
                    UpdatedAt = DateTime.Now
                };
                
                var userId = await _userRepository.CreateAsync(localUser);
                localUser.Id = userId;
            }
            else
            {
                // 更新本地用户信息
                localUser.FullName = uumUser.PeopleName ?? string.Empty;
                localUser.PasswordHash = uumUser.UserPassword ?? string.Empty;
                localUser.UpdatedAt = DateTime.Now;
                await _userRepository.UpdateAsync(localUser);
            }

            // 更新最后登录时间
            await _userRepository.UpdateLastLoginAsync(localUser.Id);

            // 生成JWT Token
            var token = GenerateJwtToken(localUser);
            var expiresAt = DateTime.UtcNow.AddHours(24);

            return new LoginResponse
            {
                Token = token,
                Id = localUser.Id,
                Username = localUser.Username,
                FullName = localUser.FullName,
                Role = localUser.Role,
                UserPhone = !string.IsNullOrWhiteSpace(uumUser.UserPhone) ? uumUser.UserPhone : string.Empty,
                ExpiresAt = expiresAt
            };
        }

        public string GenerateJwtToken(User user)
        {
            var jwtKey = _configuration["Jwt:Key"] ?? "your-super-secret-jwt-key-that-is-at-least-32-characters-long";
            var key = Encoding.ASCII.GetBytes(jwtKey);

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                    new Claim(ClaimTypes.Name, user.Username),
                    new Claim(ClaimTypes.Role, user.Role),
                    new Claim("full_name", user.FullName ?? "")
                }),
                Expires = DateTime.UtcNow.AddHours(24),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }

        public string HashPassword(string password)
        {
            return HashPasswordMD5(password);
        }

        public bool VerifyPassword(string password, string hash)
        {
            var hashedPassword = HashPasswordMD5(password);
            return hashedPassword == hash;
        }

        private string HashPasswordMD5(string password)
        {
            using (var md5 = MD5.Create())
            {
                var inputBytes = Encoding.UTF8.GetBytes(password);
                var hashBytes = md5.ComputeHash(inputBytes);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
            }
        }

        /// <summary>
        /// 获取客户端IP地址（简化版本，实际项目中可能需要从HttpContext获取）
        /// </summary>
        /// <returns>客户端IP地址</returns>
        private string GetClientIpAddress()
        {
            // 在实际项目中，这里应该从HttpContext获取真实的客户端IP
            // 这里返回一个默认值，避免编译错误
            return "127.0.0.1";
        }
    }
}